using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;

namespace OpenFlashChartLib
{
    public class Graph: Control
    {
        private Title _title = new Title();
        private GraphLegend _xLegend = new GraphLegend(GraphLegend.XGraphLegendToken);
        private GraphLegend _yLegend = new GraphLegend(GraphLegend.YGraphLegendToken);
        private GraphLabelStyle _xLabelStyle = new GraphLabelStyle(GraphLabelStyle.XLabelStyleToken);
        private GraphLabelStyle _yLabelStyle = new GraphLabelStyle(GraphLabelStyle.YLabelStyleToken);
        private GraphTicks _xTicks = new GraphTicks(GraphTicks.XTicksToken);
        private GraphTicks _yTicks = new GraphTicks(GraphTicks.YTicksToken);
        private GraphColor _color = new GraphColor();
        private KeyValuePairGeneric<int> _yMin = new KeyValuePairGeneric<int>("y_min");
        private KeyValuePairGeneric<int> _yMax = new KeyValuePairGeneric<int>("y_max");
        private KeyValueList _xLabels = new KeyValueList("x_labels");
        private NotifyCollection<IDataRender> _values = new NotifyCollection<IDataRender>();
        private List<IRender> _attributes = new List<IRender>();
        private List<IRender> _renderes;
        private KeyValuePair _toolTip = new KeyValuePair("tool_tip");
        private KeyValuePair _backgroundColor = new KeyValuePair(Tokens.BackgroundColor);
        private KeyValuePairGeneric<int> _numDecimails = new KeyValuePairGeneric<int>("num_decimals", 3);

        public Graph()
        {
            _renderes = new List<IRender>();
            _renderes.Add(_title);
            _renderes.Add(_xLegend);
            _renderes.Add(_yLegend);
            _renderes.Add(_xLabelStyle);
            _renderes.Add(_yLabelStyle);
            _renderes.Add(_xTicks);
            _renderes.Add(_color);
            _renderes.Add(_yMin);
            _renderes.Add(_yMax);
            _renderes.Add(_xLabels);
            _renderes.Add(_toolTip);
            _renderes.Add(_numDecimails);
            _values.Change += new ChangedEventHandler<IDataRender>(_values_Change);
        }

        void _values_Change(object sender, ChangedEventArgs<IDataRender> e)
        {
            switch(e.Action)
            {
                case ChangedAction.Insert:
                case ChangedAction.Add:
                    IDataRender changed = e.ChangedItem;
                    if (XLabels.Values.Count > 0 && changed.ValuesRenderer.Count != XLabels.Values.Count)
                        throw new ArgumentException("The count of x label and values must be equal");
                    // Add suffix to the new item
                    NotifyCollection<IDataRender> collection = (NotifyCollection<IDataRender>) sender;
                    if (collection.Count > 0)
                    {
                        e.ChangedItem.ValuesRenderer.ValueSet = collection.Count + 1;
                        e.ChangedItem.GraphTypeRenderer.ValueSet = collection.Count + 1;
                        e.ChangedItem.ToolTipRenderer.ValueSet = collection.Count + 1;
                    }
                    break;
                case ChangedAction.Remove:
                    int i = 0;
                    foreach (IDataRender render in _values)
                    {
                        render.GraphTypeRenderer.ValueSet = i;
                        render.ValuesRenderer.ValueSet = i;
                        render.ToolTipRenderer.ValueSet = i;
                        i++;
                    }
                    break;
                case ChangedAction.Set:
                    changed = e.ChangedItem;
                    if (XLabels.Values.Count > 0 && changed.ValuesRenderer.Count != XLabels.Values.Count)
                        throw new ArgumentException("The count of x label and values must be equal");
                    break;
            }
        }

        public Title Title
        {
            get { return _title; }
        }

        public GraphLegend XLegend
        {
            get { return _xLegend; }
        }

        public GraphLegend YLegend
        {
            get { return _yLegend; }
        }

        public GraphLabelStyle XLabelStyle
        {
            get { return _xLabelStyle; }
        }

        public GraphLabelStyle YLabelStyle
        {
            get { return _yLabelStyle; }
        }

        public GraphTicks XTicks
        {
            get { return _xTicks; }
        }

        public GraphTicks YTicks
        {
            get { return _yTicks; }
        }

        public GraphColor Color
        {
            get { return _color; }
        }

        public int YMin
        {
            get { return _yMin.Value; }
            set { _yMin.Value = value; }
        }

        public int YMax
        {
            get { return _yMax.Value; }
            set{ _yMax.Value = value;}
        }

        public NotifyCollection<IDataRender> Values
        {
            get { return _values; }
        }

        public IList<IRender> Attributes
        {
            get { return _attributes; }
        }

        public KeyValueList XLabels
        {
            get { return _xLabels; }
        }

        public string ToolTip
        {
            get { return _toolTip.Value; }
            set { _toolTip.Value = value; }
        }

        public string BackgroundColor
        {
            get { return _backgroundColor.Value; }
            set { _backgroundColor.Value = value; }
        }

        public int NumDecimals
        {
            get { return _numDecimails.Value; }
            set { _numDecimails.Value = value; }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (PieChart())
            {
                // The pie does not have xLabelStyle or yLabelStyle
                // If leave them it will render improperly
                // So copy values of _xLabelStyle to pie properties
                PieGraphType pie = GetPieRenderer();
                pie.FontSize = _xLabelStyle.Size;
                pie.LabelColor = _xLabelStyle.Color;
                // And remove 
                _xLabels.Key = PieGraphType.PieLabelsToken;
                // The #comma# does not properly shown in the pie chart
                // Remove it
                for (int i = 0; i < _xLabels.Values.Count; i++)
                {
                    if (_xLabels.Values[i] != null)
                        _xLabels.Values[i] = _xLabels.Values[i].ToString().Replace(',', ' ');
                }
                _yLabelStyle.Values.Clear();
                _yLegend.Values.Clear();
                _xLabelStyle.Values.Clear(); 
   
            }
            foreach (IRender render in _renderes)
            {
                render.Render(writer);
            }
            foreach (IDataRender value in _values)
            {
                value.GraphTypeRenderer.Render(writer);
                value.ValuesRenderer.Render(writer);
                value.ToolTipRenderer.Render(writer);
            }
            foreach (IRender att in _attributes)
            {
                att.Render(writer);
            }
        }

        public PieGraphType GetPieRenderer()
        {
            foreach (IDataRender render in _values)
            {
                if (render.GraphTypeRenderer is PieGraphType)
                    return (PieGraphType)render.GraphTypeRenderer;
            }
            return null;
        }

        public bool PieChart()
        {
            foreach (IDataRender render in _values)
            {
                if (render.GraphTypeRenderer is PieGraphType)
                    return true;
            }
            return false;
        }
    }
}
